package mgodb

import (
	"github.com/facebookgo/inject"

	"github.com/globalsign/mgo"
	"github.com/globalsign/mgo/bson"
	"github.com/pkg/errors"
	"jgt-oper/src/model"
	"jgt-oper/src/schema"
	"jgt-oper/src/service/mongo"
)

// cEnterpriseAccount 企业管理表名
const cEnterpriseAccount = "oper_enterprise_account"
// cEnterpriseAccountLogs 企业金融账户充值消费纪录表
const cEnterpriseAccountLogs = "oper_enterprise_account_logs"

// EnterpriseAccount 企业金融账户管理
type EnterpriseAccount struct {
	DB *mongo.DB
}

// Init 初始化
func (a *EnterpriseAccount) Init(g *inject.Graph, db *mongo.DB) {
	a.DB = db

	// 初始化mongo索引
	a.DB.C(cEnterpriseAccount, func(c *mgo.Collection) error {
		c.EnsureIndex(mgo.Index{
			Key:    []string{"enterprise_id", "deleted"},
			Unique: true,
		})
		c.EnsureIndexKey("enterprise_id")
		return nil
	})
	// 初始化mongo索引
	a.DB.C(cEnterpriseAccountLogs, func(c *mgo.Collection) error {
		c.EnsureIndexKey("enterprise_id")
		c.EnsureIndexKey("record_id")
		c.EnsureIndexKey("enterprise_account_id")
		return nil
	})

	var val model.IEnterpriseAccount = a
	g.Provide(&inject.Object{Value: val, Name: "IEnterpriseAccount"})
}

// AccountOpen 账户开通
func (a *EnterpriseAccount) AccountOpen(account *schema.EnterpriseFinanceAccount) error {
	query := bson.M{
		"enterprise_id": account.EnterpriseID,
		"account_state": 1,
	}
	//查询企业金融账户并校验是否存在
	err := a.DB.C(cEnterpriseAccount, func(c *mgo.Collection) error {
		total, err := c.Find(query).Count()
		if err != nil {
			return err
		}
		if total > 1 {
			return errors.New("不能创建多个企业金融账户")
		}
		return nil
	})
	if err != nil {
		return err
	}
	//创建企业金融账户
	err = a.DB.C(cEnterpriseAccount, func(c *mgo.Collection) error {
		id, err := a.DB.IncrID(cEnterpriseAccount)
		if err != nil {
			return err
		}
		account.ID = id
		return c.Insert(account)
	})
	if err != nil {
		return errors.Wrapf(err, "创建企业金融账户发生错误")
	}
	return nil
}

// AccountPay 账户支付(充值或消费)
func (a *EnterpriseAccount) AccountPay(pay *schema.BalanceOfPayments) error {
	query := bson.M{
		"enterprise_id": pay.EnterpriseID,
		"account_state": 1,
	}
	enterpriseAccount := new(schema.EnterpriseFinanceAccount)
	//校验账户数量
	err := a.DB.C(cEnterpriseAccount, func(c *mgo.Collection) error {
		total, err := c.Find(query).Count()
		if err != nil {
			return err
		}
		if total > 1 || total < 1 {
			return errors.New("企业金融账户信息错误(多个账户、或不存在)")
		}
		return c.Find(query).One(enterpriseAccount)
	})
	if err != nil {
		return err
	}
	//插入充值记录
	pay.AccountBalanceCurrent = enterpriseAccount.AccountBalance + pay.PaymentAmount
	if pay.AccountBalanceCurrent < 0 {
		return errors.New("账户余额不足")
	}
	pay.PaymentState = 1
	err = a.DB.C(cEnterpriseAccountLogs, func(c *mgo.Collection) error {
		id, err := a.DB.IncrID(cEnterpriseAccountLogs)
		if err != nil {
			return err
		}
		pay.ID = id
		return c.Insert(pay)
	})
	if err != nil {
		return errors.Wrapf(err, "创建企业金融账户发生错误")
	}
	//更新企业账户信息:当前充值或消费记录的record_id 计入账户的最后记录指向，并修改账户余额
	err = a.DB.C(cEnterpriseAccount, func(c *mgo.Collection) error {
		return c.Update(bson.M{"record_id": enterpriseAccount.RecordID, "account_state": 1}, bson.M{"$set": bson.M{"account_balance": pay.AccountBalanceCurrent, "lastpaymentid": pay.RecordID}})
	})
	if err != nil {
		return errors.Wrapf(err, "更新企业金融账户余额和最后支付记录指向时 出错")
	}
	return nil
}

// AccountDetail 查询金融账户
func (a *EnterpriseAccount) AccountDetail(enterpriseID string) (*schema.EnterpriseFinanceAccount, error) {
	var (
		enterpriseAccount *schema.EnterpriseFinanceAccount
		err               error
	)
	enterpriseAccount = new(schema.EnterpriseFinanceAccount)
	err = a.DB.C(cEnterpriseAccount, func(c *mgo.Collection) error {
		return c.Find(bson.M{"enterprise_id": enterpriseID, "account_closed_time": 0}).One(enterpriseAccount)
	})
	if err != nil {
		return nil, err
	}
	return enterpriseAccount, nil
}

// AccountPaymentList 查询指定账户的账务记录列表
func (a *EnterpriseAccount) AccountPaymentList(enterpriseAccountID string, pageIndex, pageSize uint) ([]*schema.BalanceOfPayments, int, error) {
	var (
		listPayment []*schema.BalanceOfPayments
		total       int
		err         error
	)
	query := bson.M{
		"enterprise_account_id": enterpriseAccountID,
		"payment_state":         1,
	}
	listPayment = make([]*schema.BalanceOfPayments, 0)
	err = a.DB.C(cEnterpriseAccountLogs, func(c *mgo.Collection) error {
		total, err = c.Find(query).Count()
		if err != nil {
			return err
		}
		return c.Find(query).Sort("paymenttime").Skip(int((pageIndex - 1) * pageSize)).Limit(int(pageSize)).All(&listPayment)
	})
	return listPayment, total, nil

}
